﻿using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Text;
using VisionCloud.Domain.Common;
using VisionCloud.Utility;
using VisionCloud.Utility.Extensions;

namespace VisionCloud.Domain.Filters
{
    /// <summary>
    /// 全局异常处理过滤器
    /// </summary>
    public class ExceptionHandleAttribute : ExceptionFilterAttribute
    {
        private readonly ILogger<ExceptionHandleAttribute> logger;
        private readonly IWebHostEnvironment hostingEnvironment;

        public ExceptionHandleAttribute(ILogger<ExceptionHandleAttribute> logger, IWebHostEnvironment hostingEnvironment)
        {
            this.logger = logger;
            this.hostingEnvironment = hostingEnvironment;
        }

        /// <summary>
        /// 处理异常
        /// </summary>
        /// <param name="context"></param>
        public override async void OnException(ExceptionContext context)
        {
            var result = new ContentResult();
            if (context.Exception is OperationException operation)
            {
                result.Content = JsonConvert.SerializeObject(new ApiResult(operation.Code, operation.Message));
                context.Result = result;
                return;
            }

            if (context.Exception is ArgumentException)
            {
                result.Content = JsonConvert.SerializeObject(new ApiResult(AjaxCode.Error, context.Exception.Message));
                context.Result = result;
                return;
            }

            if (context.Exception is OperationCanceledException)
            {
                logger.LogInformation($"Request was cancelled：{context.HttpContext.Request.Path}");
                context.ExceptionHandled = true;
                return;
            }

            if (context.Exception is BadHttpRequestException)
            {
                logger.LogError($"Bad http request：{context.HttpContext.Request.Path}");
            }
            // 错误日志文件输出
            var exmessage = new StringBuilder();
            exmessage.AppendLine("StackTrace:" + (context.Exception.StackTrace == null ? string.Empty : context.Exception.StackTrace));
            exmessage.AppendLine("Source:" + (context.Exception.Source == null ? string.Empty : context.Exception.Source));
            exmessage.AppendLine("Message:" + context.Exception.Message);
            exmessage.AppendLine("InnerExceptionMessage:" + (context.Exception.InnerException == null ? string.Empty : context.Exception.InnerException.Message));
            try
            {
                logger.LogError(exmessage.ToString());
            }
            catch
            {
                if (context.Exception.InnerException != null)
                    logger.LogError(exmessage.ToString());
            }

            if (hostingEnvironment.IsDevelopment() || hostingEnvironment.IsLocal())
            {
                result.Content = JsonConvert.SerializeObject(new ApiResult(AjaxCode.Error, context.Exception.Message));
            }
            else
            {
                result.Content = JsonConvert.SerializeObject(new ApiResult(AjaxCode.Error, StartupServer.CommonLocalizer["YB0459"].Value));
            }
            context.Result = result;
            context.ExceptionHandled = true;
        }
    }
}